package com.oa.service.user.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.oa.mapper.user.*;
import com.oa.pojo.*;
import com.oa.service.user.OAService;
import com.oa.vo.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class OAImpl implements OAService {
    @Autowired
    private OAMapper oaMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private EmpMappper empMappper;
    @Autowired
    private PositionMapper positionMapper;
    @Autowired
    private AttendanceMapper attendanceMapper;
    @Autowired
    private AttendCountMapper attendCountMapper;

    @Override
    public List<OaApproval> getAllOA() {
        return oaMapper.selectList(null);
    }

    /**
     * @param id
     * @return
     */
    @Override
    public List<OaApproval> getOAByUsers(Integer id) {
        return getOAByUser(id);
    }


    /**
     * 用于用户查询自己提交OA的公共方法
     *
     * @param id 用户id
     * @return
     */
    private List<OaApproval> getOAByUser(Integer id) {
        List<OaApproval> oaApprovals = oaMapper.
                selectList(new QueryWrapper<OaApproval>()
                        .eq("submitter_id", id));
        for (OaApproval oaApproval : oaApprovals) {
            oaApproval.setSubmitter(userMapper.selectOne(new QueryWrapper<Emp>().eq("emp_id", oaApproval.getSubmitterId())).getEmpName());
            oaApproval.setApprover(userMapper.selectOne(new QueryWrapper<Emp>().eq("emp_id", oaApproval.getApproverId())).getEmpName());
        }
        return oaApprovals;
    }

    /**
     * 新增oa申请
     *
     * @param oaApproval 封装的oa对象
     */
    @Override
    @Transactional
    public void submitOA(OaApproval oaApproval) {
        Date date = new Date();
        /*获取提交OA员工的部门id*/
        Integer positionId = empMappper.selectOne(new QueryWrapper<Emp>().eq("emp_id", oaApproval.getSubmitterId())).getPositionId();
        /*获取该员工的父级部门id*/
        Integer parentId = positionMapper.selectOne(new QueryWrapper<Position>().eq("position_id", positionId)).getParentId();
        /*通过父级部门id获取父级部门deptId*/
        Integer depId = positionMapper.selectOne(new QueryWrapper<Position>().eq("position_id", parentId)).getDepId();
        /*通过depId获取该部门主管id*/
        Integer managerId = deptMapper.selectOne(new QueryWrapper<Department>().eq("dep_id", depId)).getManagerId();
        oaApproval.setApproverId(managerId).setItemStatus(1).setSubmitTime(date).setEditTime(date);
        oaMapper.insert(oaApproval);
    }

    @Override
    public OaApproval getOaById(Integer OAId) {
        return oaMapper.selectOne(new QueryWrapper<OaApproval>().eq("id", OAId));
    }

    @Override
    public void updateOA(OaApproval oaApproval) {
        Date date = new Date();
        oaApproval.setEditTime(date);
        oaApproval.setItemStatus(1);
        Integer itemStatus = oaApproval.getItemStatus();
        oaMapper.updateById(oaApproval);
    }

    @Override
    public void deleteOA(Integer oaId) {
        oaMapper.deleteById(oaId);
    }

    /**
     * 审核者查看OA
     *
     * @param adminId
     * @return
     */
    @Override
    public List<OaApproval> getOAByAdmin(Integer adminId) {
        List<OaApproval> oaApprovals = oaMapper.
                selectList(new QueryWrapper<OaApproval>()
                        .eq("approver_id", adminId).ne("item_status", 3).ne("item_status", 2));
        for (OaApproval oaApproval : oaApprovals) {
            oaApproval.setSubmitter(userMapper.selectOne(new QueryWrapper<Emp>().eq("emp_id", oaApproval.getSubmitterId())).getEmpName());
            oaApproval.setApprover(userMapper.selectOne(new QueryWrapper<Emp>().eq("emp_id", oaApproval.getApproverId())).getEmpName());
        }
        return oaApprovals;
    }

    @Override
    public PageResult getOAList(PageResult pageResult) {
        String userRole = pageResult.getUserRole();
        Page<OaApproval> page = new Page<>(pageResult.getPageNum(), pageResult.getPageSize());
        QueryWrapper<OaApproval> queryWrapper = new QueryWrapper<>();
        boolean flag = StringUtils.hasLength(pageResult.getQuery());
        queryWrapper.like(flag, "item_name", pageResult.getQuery()).eq(userRole, pageResult.getEmpId());
        page = oaMapper.selectPage(page, queryWrapper);
        List<OaApproval> records = page.getRecords();
        for (OaApproval record : records) {
            record.setSubmitter(userMapper.selectOne(new QueryWrapper<Emp>().eq("emp_id", record.getSubmitterId())).getEmpName());
            record.setApprover(userMapper.selectOne(new QueryWrapper<Emp>().eq("emp_id", record.getApproverId())).getEmpName());
            subStatusDefine(record);
        }
        pageResult.setRows(page.getRecords()).setTotal(page.getTotal());

        return pageResult;
    }

    /**
     * 审核OA
     * 审核通过后同步考勤相关数据
     *
     * @param oaApproval
     */
    @Override
    public void ApproveOA(OaApproval oaApproval) {
        Integer itemStatus = oaApproval.getItemStatus();
        //获取oa分类的id 1.请假 2.出差 3.离职
        Integer sortingId = oaApproval.getSortingId();
        System.out.println("itemStatus:" + itemStatus);
        oaMapper.updateById(oaApproval);
        //定义不同oa申请需要返回的结果集
        Map<Integer, Map<String, String>> resultMap = new HashMap<>();
        HashMap<String, String> map = new HashMap<>();
        map.put("overtimeHours", "请假,请单独统计时间");
        map.put("workTime", "请假,请单独统计");
        map.put("attendanceStatus", "请假");
        HashMap<String, String> map2 = new HashMap<>();
        map2.put("overtimeHours", "出差,请单独统计时间");
        map2.put("workTime", "出差,请单独统计");
        map2.put("attendanceStatus", "出差");
        resultMap.put(1, map);
        resultMap.put(2, map2);
        //如果考勤结果为通过则执行出席表的同步修改
        if (itemStatus == 2) {
            if (sortingId == 1) {
                doAttendanceAfterApproveOA(oaApproval, resultMap.get(1));
            } else if (sortingId == 2) {
                doAttendanceAfterApproveOA(oaApproval, resultMap.get(2));
            }
        }

    }

    /**
     * 实现OA通过后的每日考勤增加
     * #TODO需要补全逻辑
     *
     * @param oaApproval
     */
    public void doAttendanceAfterApproveOA(OaApproval oaApproval, Map<String, String> map) {
        Date startTime = oaApproval.getStartTime();
        Date endTime = oaApproval.getEndTime();
        String submitterIdStr = StrUtil.toString(oaApproval.getSubmitterId());
        String submitter = oaApproval.getSubmitter();
        //根据OA申请的日期生成在attendance的attendanceIndex,一定不为空
        ArrayList<String> dateList = new ArrayList<>();
        while (!startTime.after(endTime)) {
            String format = DateUtil.format(startTime, "yyyy-MM-dd");
            dateList.add(submitterIdStr + format);
            startTime = DateUtil.offsetDay(startTime, 1);
        }
        //删除对应的出勤表单
        attendanceMapper.delete(new QueryWrapper<Attendance>().in("Attendance_index", dateList));
        //新建出勤对象list,用于存放插入的数据
        List<Attendance> attendances = new ArrayList<>();
        //用于批量生成考勤所有的时间对
        attendances = generateAttendanceList(dateList, attendances, submitter, map);
        //在考勤统计表中插入对应数据
        List<AttendanceCount> attendanceCounts = generateAttendanceCountList(dateList, attendances);
        attendCountMapper.mysqlInsertAllBatch(attendanceCounts);
        attendanceMapper.mysqlInsertAllBatch(attendances);

    }

    /**
     * 在考勤统计表中插入对应数据
     *
     * @param dateList
     */
    private List<AttendanceCount> generateAttendanceCountList(ArrayList<String> dateList, List<Attendance> attendances) {
        String attendanceStatus = attendances.get(0).getAttendanceStatus();
        ArrayList<AttendanceCount> attendanceCounts = new ArrayList<>();
        for (String index : dateList) {
            attendanceCounts.add(
                    new AttendanceCount().setAttendanceDay(DateUtil.parse(index.substring(8)))
                            .setEmpId(Integer.valueOf(index.substring(0, 8)))
                            .setAttendanceNum(Convert.convert(Integer.class, attendanceStatus.contains("正常")))
                            .setAbsentNum(Convert.convert(Integer.class, attendanceStatus.contains("异常")))
                            .setLeaveNum(Convert.convert(Integer.class, attendanceStatus.contains("请假")))
                            .setBusNum(Convert.convert(Integer.class, attendanceStatus.contains("出差")))

            );
        }
        return attendanceCounts;
    }

    /**
     * 生成每天的考勤记录方法
     *
     * @param dateList    attendanceIndex列表
     * @param attendances attendance对象的list,用于返回后插入出勤表
     * @return
     */
    public List<Attendance> generateAttendanceList(List<String> dateList, List<Attendance> attendances, String submitter, Map<String, String> map) {
        //定义每天上班时间
        String morningTime = " 08:30:00";
        //定义每天下班时间
        String afternoonTime = " 17:30:00";
        //定义日期的字符串
        for (String index : dateList) {
            attendances.add(
                    new Attendance().setAttendanceIndex(index)
                            .setAttendanceTime(DateUtil.parse(index.substring(8) + morningTime))
                            .setCloseTime(DateUtil.parse(index.substring(8) + afternoonTime))
                            .setOvertimeHours(map.get("overtimeHours"))
                            .setWorkTime(map.get("workTime"))
                            .setAttendanceStatus(map.get("attendanceStatus"))
                            .setEmpId(Integer.valueOf(index.substring(0, 8)))
                            .setEmpName(submitter)
            )
            ;
        }

        return attendances;
    }

    /**
     * 返回提交OA状态的布尔值,未通过返回true
     *
     * @return
     */
    public void subStatusDefine(OaApproval oaApproval) {
        Integer itemStatus = oaApproval.getItemStatus();
        if (itemStatus == 3 || itemStatus == 2) {
            oaApproval.setSubStatus(true);
        } else {
            oaApproval.setSubStatus(false);
        }
    }

}
